﻿using System;
using System.Diagnostics;
using System.Reflection;
using log4net;
using Interfaces = TfsCloudDeploy.Deployment.Framework.Interfaces;
using System.IO;

namespace TfsCloudDeploy.Deployment.Framework
{
    /// <summary>
    /// Provides logging utility methods that wrap around log4net.
    /// </summary>
    /// <remarks>
    /// This class mitigates the need to reference log4net in each and every project where we need logging
    /// (that's almost all projects). Having our own wrapper allows us to control what we can change and
    /// customize with the logging. And the Framework assembly should be referenced in all projects anyway.
    /// </remarks>
    public class Log : Interfaces.ILog
    {
        #region Private Fields

        private ILog _log;

        #endregion

        #region Constructors

        private Log()
        {
            // The default constructor is intentionally "private" to prevent instantiating this class without a class name or type.
        }

        public Log(string name)
        {
            _log = LogManager.GetLogger(name);
        }

        public Log(Type type)
        {
            _log = LogManager.GetLogger(type);
        }

        public Log(Assembly repositoryAssembly, string name)
        {
            _log = LogManager.GetLogger(repositoryAssembly, name);
        }

        public Log(Assembly repositoryAssembly, Type type)
        {
            _log = LogManager.GetLogger(repositoryAssembly, type);
        }

        public Log(string repository, string name)
        {
            _log = LogManager.GetLogger(repository, name);
        }

        public Log(string repository, Type type)
        {
            _log = LogManager.GetLogger(repository, type);
        }

        #endregion

        #region Interfaces.ILog Members

        public bool IsDebugEnabled
        {
            get { return _log.IsDebugEnabled; }
        }

        public bool IsErrorEnabled
        {
            get { return _log.IsErrorEnabled; }
        }

        public bool IsFatalEnabled
        {
            get { return _log.IsFatalEnabled; }
        }

        public bool IsInfoEnabled
        {
            get { return _log.IsInfoEnabled; }
        }

        public bool IsWarnEnabled
        {
            get { return _log.IsWarnEnabled; }
        }

        public void Debug(object message, Exception exception)
        {
            _log.Debug(message, exception);
        }

        public void Debug(object message)
        {
            _log.Debug(message);
        }

        public void DebugFormat(IFormatProvider provider, string format, params object[] args)
        {
            _log.DebugFormat(provider, format, args);
        }

        public void DebugFormat(string format, params object[] args)
        {
            _log.DebugFormat(format, args);
        }

        public void Error(object message, Exception exception)
        {
            _log.Error(message, exception);
        }

        public void Error(object message)
        {
            _log.Error(message);
        }

        public void ErrorFormat(IFormatProvider provider, string format, params object[] args)
        {
            _log.ErrorFormat(provider, format, args);
        }

        public void ErrorFormat(string format, params object[] args)
        {
            _log.ErrorFormat(format, args);
        }

        public void Fatal(object message, Exception exception)
        {
            _log.Fatal(message, exception);
        }

        public void Fatal(object message)
        {
            _log.Fatal(message);
        }

        public void FatalFormat(IFormatProvider provider, string format, params object[] args)
        {
            _log.FatalFormat(provider, format, args);
        }

        public void FatalFormat(string format, params object[] args)
        {
            _log.FatalFormat(format, args);
        }

        public void Info(object message, Exception exception)
        {
            _log.Info(message, exception);
        }

        public void Info(object message)
        {
            _log.Info(message);
        }

        public void InfoFormat(IFormatProvider provider, string format, params object[] args)
        {
            _log.InfoFormat(provider, format, args);
        }

        public void InfoFormat(string format, params object[] args)
        {
            _log.InfoFormat(format, args);
        }

        public void Warn(object message, Exception exception)
        {
            _log.Warn(message, exception);
        }

        public void Warn(object message)
        {
            _log.Warn(message);
        }

        public void WarnFormat(IFormatProvider provider, string format, params object[] args)
        {
            _log.WarnFormat(provider, format, args);
        }

        public void WarnFormat(string format, params object[] args)
        {
            _log.WarnFormat(format, args);
        }

        #endregion

        #region Static Methods

        public static void ConfigureAndWatch(string loggingConfigFilePath)
        {
            log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo(loggingConfigFilePath));
        }

        #endregion
    }
}
